﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ShevaEngine.Core.Interfaces;
using ShevaEngine.Core.Modules.Graphics;
using ShevaEngine.Core.Modules.Graphics.Cameras;
using ShevaEngine.Core.Modules.Materials;
using ShevaEngine.Core.Modules.Models;
using ShevaEngine.Core.Modules.Scenes;

namespace ShevaEngine2.Tools
{
    /// <summary>
    /// Gizmo component.
    /// </summary>
    public class Gizmo : SceneObject, IUpdateAble
    {
        /// <summary>Viewport.</summary>
        private GraphicsViewport Viewport;
        /// <summary>Selected scene objects.</summary>
        public ObservableCollection<SceneObject> SelectedObjects;
        /// <summary>Axis draw call key.</summary>
        private DrawCallKey VertexColorDrawCallKey;
        /// <summary>Axe X draw call key.</summary>
        private DrawCallKey AxeXColorDrawCallKey;
        /// <summary>Axe Y draw call key.</summary>
        private DrawCallKey AxeYColorDrawCallKey;
        /// <summary>Axe Z draw call key.</summary>
        private DrawCallKey AxeZColorDrawCallKey;
        /// <summary>Axis draw call.</summary>
        private UserPrimitivesDrawCall<VertexPositionColor> AxisDrawCall;
        /// <summary>Translation model.</summary>
        private ShevaModel ConeModel;
        /// <summary>Rotation model.</summary>
        private ShevaModel RotationModel;
        /// <summary>Scale model.</summary>
        private ShevaModel ScaleModel;        
        /// <summary>Quads.</summary>
        private Quad[] Quads;



        /// <summary>Precision mode.</summary>
        private bool precisionMode = false;
        /// <summary>Screen scale.</summary>
        private Matrix screenScaleMatrix;
        /// <summary>Screen scale.</summary>
        private float screenScale;
        /// <summary>Position.</summary>
        private Vector3 position = Vector3.Zero;
        /// <summary>Rotation matrix.</summary>
        private Matrix rotationMatrix = Matrix.Identity;
        /// <summary>Rotation quaternion.</summary>
        private Quaternion Rotation { get { return Quaternion.CreateFromRotationMatrix(rotationMatrix); } }
        /// <summary>Local forward.</summary>
        private Vector3 localForward = Vector3.Forward;
        /// <summary>Local Up.</summary>
        private Vector3 localUp = Vector3.Up;
        /// <summary>Local right.</summary>
        private Vector3 localRight;
        /// <summary>Object Oriented World.</summary>
        private Matrix objectOrientedWorld;
        /// <summary>Axis aligned world.</summary>
        private Matrix axisAlignedWorld;
        /// <summary>Model local space.</summary>
        private Matrix[] ModelLocalSpace;
        /// <summary>The matrix used to apply to your whole scene, usually matrix.identity (default scale, origin on 0,0,0 etc.).</summary> 
        public Matrix sceneWorld;
        
        /// <summary>Line length.</summary>
        private float lineLength = 3f;
        /// <summary>Line offest.</summary>
        private float lineOffset = 0.25f;
        
        /// <summary>Axis colors.</summary>
        private Color[] axisColors;
        /// <summary>Highlight color.</summary>
        private Color highlightColor;
        /// <summary>Axis text offset.</summary>
        private Vector3 axisTextOffset = new Vector3(0, 0.5f, 0);
        /// <summary>Active Axis.</summary>
        public GizmoAxis ActiveAxis = GizmoAxis.None;
        /// <summary>Active mode.</summary>
        public GizmoMode ActiveMode = GizmoMode.Translate;        

        
        private float boxThickness = 0.05f;
        private BoundingOrientedBox X_Box
        {
            get
            {
                return new BoundingOrientedBox(Vector3.Transform(new Vector3((lineLength / 2) + (lineOffset * 2), 0, 0), World),
                    Vector3.Transform(new Vector3(lineLength / 2, 0.2f, 0.2f), screenScaleMatrix), Rotation);
            }
        }

        private BoundingOrientedBox Y_Box
        {
            get
            {
                return new BoundingOrientedBox(Vector3.Transform(new Vector3(0, (lineLength / 2) + (lineOffset * 2), 0), World),
                    Vector3.Transform(new Vector3(0.2f, lineLength / 2, 0.2f), screenScaleMatrix), Rotation);
            }
        }

        private BoundingOrientedBox Z_Box
        {
            get
            {
                return new BoundingOrientedBox(Vector3.Transform(new Vector3(0, 0, (lineLength / 2) + (lineOffset * 2)), World),
                    Vector3.Transform(new Vector3(0.2f, 0.2f, lineLength / 2), screenScaleMatrix), Rotation);
            }
        }

        private BoundingOrientedBox XZ_Box
        {
            get
            {
                return new BoundingOrientedBox(Vector3.Transform(new Vector3(lineOffset, 0, lineOffset), World),
                    Vector3.Transform(new Vector3(lineOffset, boxThickness, lineOffset), screenScaleMatrix), Rotation);
            }
        }

        private BoundingOrientedBox XY_Box
        {
            get
            {
                return new BoundingOrientedBox(Vector3.Transform(new Vector3(lineOffset, lineOffset, 0), World),
                    Vector3.Transform(new Vector3(lineOffset, lineOffset, boxThickness), screenScaleMatrix), Rotation);
            }
        }

        private BoundingOrientedBox YZ_Box
        {
            get
            {
                return new BoundingOrientedBox(Vector3.Transform(new Vector3(0, lineOffset, lineOffset), World),
                    Vector3.Transform(new Vector3(boxThickness, lineOffset, lineOffset), screenScaleMatrix), Rotation);
            }
        }

        private float radius = 1f;
        private BoundingSphere X_Sphere
        {
            get { return new BoundingSphere(Vector3.Transform(this.AxisDrawCall.Vertices[1].Position, World), radius * screenScale); }
        }

        private BoundingSphere Y_Sphere
        {
            get { return new BoundingSphere(Vector3.Transform(this.AxisDrawCall.Vertices[7].Position, World), radius * screenScale); }
        }

        private BoundingSphere Z_Sphere
        {
            get { return new BoundingSphere(Vector3.Transform(this.AxisDrawCall.Vertices[13].Position, World), radius * screenScale); }
        }               

        // other hotkeys:
        // Space = change of transformationSpace
        // Space + Shift = change of pivotType
        // 1, 2, 3, 4 = change of transformation-mode

        private float inputScale;

        /// <summary>
        /// The value to adjust all transformation when precisionMode is active.
        /// </summary>
        private float precisionModeScale = 0.1f;
        
        

        // -- Translation Variables -- //
        Vector3 translationDelta;
        Vector3 lastIntersectionPosition;
        Vector3 intersectPosition;
        private const float translationClampDistance = 1000;


        public bool SnapEnabled = true;

        public float TranslationSnapValue = 5;
        public float RotationSnapValue = 30;
        public float ScaleSnapValue = 0.5f;

        private Vector3 translationScaleSnapDelta;        


        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="world"></param>
        public Gizmo(GraphicsViewport viewport, Matrix world)            
        {
            this.Viewport = viewport;
            this.sceneWorld = world;
            this.SelectedObjects = new ObservableCollection<SceneObject>();

            this.SelectedObjects.CollectionChanged += 
                new NotifyCollectionChangedEventHandler(this.SelectedObjects_CollectionChanged);

            this.Visible = false;

            this.AxeXColorDrawCallKey = new DrawCallKey(MaterialManager.Instance.GetMaterialID("MaterialBaseColor"),
                DrawCallKey.None, DrawCallKey.None, DrawCallKey.None);
            this.AxeYColorDrawCallKey = new DrawCallKey(MaterialManager.Instance.GetMaterialID("MaterialBaseColor"),
                DrawCallKey.None, DrawCallKey.None, DrawCallKey.None);
            this.AxeZColorDrawCallKey = new DrawCallKey(MaterialManager.Instance.GetMaterialID("MaterialBaseColor"),
                DrawCallKey.None, DrawCallKey.None, DrawCallKey.None);

            this.VertexColorDrawCallKey = new DrawCallKey(MaterialManager.Instance.GetMaterialID("MaterialBaseVertexColor"),
                DrawCallKey.None, DrawCallKey.None, DrawCallKey.None);

            GraphicsMaterialParametersList paramMaterial = new GraphicsMaterialParametersList();
            paramMaterial.Add(new GraphicsMaterialParameterColor("Color", Color.YellowGreen));

            this.AxeXColorDrawCallKey.MaterialParamsID =
                MaterialManager.Instance[this.AxeXColorDrawCallKey.MaterialID].GraphicsProfile.GetMaterialParametersId(paramMaterial);
            this.ConeModel = ModelManager.Instance["gizmo_translate"];
            this.ConeModel.SetupDrawCallKey(this.AxeXColorDrawCallKey);

            this.RotationModel = ModelManager.Instance["gizmo_rotate"];
            this.RotationModel.SetupDrawCallKey(this.AxeXColorDrawCallKey);
            
            this.ScaleModel = ModelManager.Instance["gizmo_scale"];
            this.ScaleModel.SetupDrawCallKey(this.AxeXColorDrawCallKey);
            
          
            // -- Set local-space offset -- //
            this.ModelLocalSpace = new Matrix[3];
            this.ModelLocalSpace[0] = Matrix.CreateWorld(new Vector3(lineLength, 0, 0), Vector3.Left, Vector3.Up);
            this.ModelLocalSpace[1] = Matrix.CreateWorld(new Vector3(0, lineLength, 0), Vector3.Down, Vector3.Left);
            this.ModelLocalSpace[2] = Matrix.CreateWorld(new Vector3(0, 0, lineLength), Vector3.Forward, Vector3.Up);

            // -- Colors: X,Y,Z,Highlight -- //
            this.axisColors = new Color[3];
            this.axisColors[0] = Color.Red;
            this.axisColors[1] = Color.Green;
            this.axisColors[2] = Color.Blue;
            this.highlightColor = Color.Gold;            

            float doubleOffset = lineOffset * 2;
            this.Quads = new Quad[3];
            this.Quads[0] = new Quad(new Vector3(lineOffset, lineOffset, 0), Vector3.Backward, Vector3.Up, doubleOffset, doubleOffset); //XY
            this.Quads[1] = new Quad(new Vector3(lineOffset, 0, lineOffset), Vector3.Up, Vector3.Right, doubleOffset, doubleOffset); //XZ
            this.Quads[2] = new Quad(new Vector3(0, lineOffset, lineOffset), Vector3.Right, Vector3.Up, doubleOffset, doubleOffset); //ZY 
            
            // fill array with vertex-data
            #region Fill Axis-Line array
            List<VertexPositionColor> vertexList = new List<VertexPositionColor>(18);

            // helper to apply colors
            Color xColor = axisColors[0];
            Color yColor = axisColors[1];
            Color zColor = axisColors[2];

            float doubleLineOffset = lineOffset * 2;

            // -- X Axis -- // index 0 - 5
            vertexList.Add(new VertexPositionColor(new Vector3(lineOffset, 0, 0), xColor));
            vertexList.Add(new VertexPositionColor(new Vector3(lineLength, 0, 0), xColor));

            vertexList.Add(new VertexPositionColor(new Vector3(doubleLineOffset, 0, 0), xColor));
            vertexList.Add(new VertexPositionColor(new Vector3(doubleLineOffset, doubleLineOffset, 0), xColor));

            vertexList.Add(new VertexPositionColor(new Vector3(doubleLineOffset, 0, 0), xColor));
            vertexList.Add(new VertexPositionColor(new Vector3(doubleLineOffset, 0, doubleLineOffset), xColor));

            // -- Y Axis -- // index 6 - 11
            vertexList.Add(new VertexPositionColor(new Vector3(0, lineOffset, 0), yColor));
            vertexList.Add(new VertexPositionColor(new Vector3(0, lineLength, 0), yColor));

            vertexList.Add(new VertexPositionColor(new Vector3(0, doubleLineOffset, 0), yColor));
            vertexList.Add(new VertexPositionColor(new Vector3(doubleLineOffset, doubleLineOffset, 0), yColor));

            vertexList.Add(new VertexPositionColor(new Vector3(0, doubleLineOffset, 0), yColor));
            vertexList.Add(new VertexPositionColor(new Vector3(0, doubleLineOffset, doubleLineOffset), yColor));

            // -- Z Axis -- // index 12 - 17
            vertexList.Add(new VertexPositionColor(new Vector3(0, 0, lineOffset), zColor));
            vertexList.Add(new VertexPositionColor(new Vector3(0, 0, lineLength), zColor));

            vertexList.Add(new VertexPositionColor(new Vector3(0, 0, doubleLineOffset), zColor));
            vertexList.Add(new VertexPositionColor(new Vector3(doubleLineOffset, 0, doubleLineOffset), zColor));

            vertexList.Add(new VertexPositionColor(new Vector3(0, 0, doubleLineOffset), zColor));
            vertexList.Add(new VertexPositionColor(new Vector3(0, doubleLineOffset, doubleLineOffset), zColor));

            this.AxisDrawCall = new UserPrimitivesDrawCall<VertexPositionColor>(
                PrimitiveType.LineList, vertexList.ToArray(), vertexList.Count / 2);
            
            #endregion
        }

        /// <summary>
        /// Selected objects changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void SelectedObjects_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (this.SelectedObjects.Count > 0)
                this.Visible = true;
            else
                this.Visible = false;
        }

        /// <summary>
        /// Method Update.
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {
            // scale for mouse.delta
            this.inputScale = (float)gameTime.ElapsedGameTime.TotalSeconds;

            this.SetPosition();

            // -- Scale Gizmo to fit on-screen -- //
            Vector3 vLength = this.Viewport.Camera.Position - position;
            float scaleFactor = 25;

            this.screenScale = vLength.Length() / scaleFactor;
            this.screenScaleMatrix = Matrix.CreateScale(new Vector3(screenScale));

            //localForward = Selection[0].Forward;
            //localUp = Selection[0].Up;

            this.localForward = Vector3.Forward;
            this.localUp = Vector3.Up;

            // -- Vector Rotation (Local/World) -- //
            this.localForward.Normalize();
            this.localRight = Vector3.Cross(localForward, localUp);
            this.localUp = Vector3.Cross(localRight, localForward);
            this.localRight.Normalize();
            this.localUp.Normalize();

            // -- Create Both World Matrices -- //
            this.objectOrientedWorld = screenScaleMatrix * Matrix.CreateWorld(position, localForward, localUp);
            this.axisAlignedWorld = screenScaleMatrix * Matrix.CreateWorld(position, sceneWorld.Forward, sceneWorld.Up);

            // Assign World
            if ((this.ActiveMode == GizmoMode.Rotate && SelectedObjects.Count > 1) ||
                (this.ActiveMode == GizmoMode.NonUniformScale && SelectedObjects.Count > 1) ||
                (this.ActiveMode == GizmoMode.UniformScale && SelectedObjects.Count > 1))
            {
                this.World = this.axisAlignedWorld;

                // align lines, boxes etc. with the grid-lines
                this.rotationMatrix.Forward = sceneWorld.Forward;
                this.rotationMatrix.Up = sceneWorld.Up;
                this.rotationMatrix.Right = sceneWorld.Right;
            }
            else
            {
                this.World = this.objectOrientedWorld;

                // align lines, boxes etc. with the selected object
                this.rotationMatrix.Forward = localForward;
                this.rotationMatrix.Up = localUp;
                this.rotationMatrix.Right = localRight;
            }

            // -- Reset Colors to default -- //
            this.ApplyColor(GizmoAxis.X, axisColors[0]);
            this.ApplyColor(GizmoAxis.Y, axisColors[1]);
            this.ApplyColor(GizmoAxis.Z, axisColors[2]);

            // -- Apply Highlight -- //
            this.ApplyColor(ActiveAxis, highlightColor);

        }

        /// <summary>
        /// Handle input.
        /// </summary>
        /// <param name="input"></param>
        //public void HandleInput(/*InputState input*/)
        //{
        //    // -- Select Gizmo Mode -- //
        //    if (input.WasKeyPressed(Keys.D1))
        //    {
        //        ActiveMode = GizmoMode.Translate;
        //    }
        //    else if (input.WasKeyPressed(Keys.D2))
        //    {
        //        ActiveMode = GizmoMode.Rotate;
        //    }
        //    else if (input.WasKeyPressed(Keys.D3))
        //    {
        //        ActiveMode = GizmoMode.NonUniformScale;
        //    }
        //    else if (input.WasKeyPressed(Keys.D4))
        //    {
        //        ActiveMode = GizmoMode.UniformScale;
        //    }

        //    // -- Cycle TransformationSpaces -- //
        //    if (input.WasKeyPressed(Keys.Space))
        //    {
        //        if (ActiveSpace == TransformSpace.Local)
        //            ActiveSpace = TransformSpace.World;
        //        else
        //            ActiveSpace = TransformSpace.Local;
        //    }

        //    // -- Cycle PivotTypes -- //
        //    if (input.WasKeyPressed(Keys.P))
        //    {
        //        if (ActivePivot == PivotType.WorldOrigin)
        //            ActivePivot = PivotType.ObjectCenter;
        //        else
        //            ActivePivot++;
        //    }

        //    // -- Toggle PrecisionMode -- //
        //    if (input.IsKeyDown(Keys.LeftShift))
        //    {
        //        precisionMode = true;
        //    }
        //    else
        //        precisionMode = false;

        //    // -- Toggle Snapping -- //
        //    if (input.WasKeyPressed(Keys.S))
        //    {
        //        SnapEnabled = !SnapEnabled;
        //    }

        //    if (input.Mouse.WasButtonPressed(MouseButtons.Left) && ActiveAxis == GizmoAxis.None)
        //    {
        //        // add to selection or clear current selection
        //        if (input.IsKeyUp(addToSelection) && input.IsKeyUp(removeFromSelection))
        //        {
        //            Selection.Clear();
        //        }

        //        PickObject(input.Mouse.Position, input.IsKeyDown(removeFromSelection));
        //    }

        //    if (Enabled)
        //    {
        //        if (input.Mouse.WasButtonPressed(MouseButtons.Left))
        //        {
        //            // reset for intersection (plane vs. ray)
        //            intersectPosition = Vector3.Zero;
        //            // reset for snapping
        //            translationScaleSnapDelta = Vector3.Zero;
        //            rotationSnapDelta = 0;
        //        }

        //        lastIntersectionPosition = intersectPosition;

        //        if (input.Mouse.WasButtonHeld(MouseButtons.Left) && ActiveAxis != GizmoAxis.None)
        //        {
        //            if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale)
        //            {
        //                #region Translate & Scale
        //                Vector3 delta = Vector3.Zero;
        //                Ray ray = ConvertMouseToRay(input.Mouse.Position);

        //                Matrix transform = Matrix.Invert(rotationMatrix);
        //                ray.Position = Vector3.Transform(ray.Position, transform);
        //                ray.Direction = Vector3.TransformNormal(ray.Direction, transform);


        //                if (ActiveAxis == GizmoAxis.X || ActiveAxis == GizmoAxis.XY)
        //                {
        //                    Plane plane = new Plane(Vector3.Forward, Vector3.Transform(position, Matrix.Invert(rotationMatrix)).Z);

        //                    float? intersection = ray.Intersects(plane);
        //                    if (intersection.HasValue)
        //                    {
        //                        intersectPosition = (ray.Position + (ray.Direction * intersection.Value));
        //                        if (lastIntersectionPosition != Vector3.Zero)
        //                        {
        //                            translationDelta = intersectPosition - lastIntersectionPosition;
        //                        }
        //                        if (ActiveAxis == GizmoAxis.X)
        //                            delta = new Vector3(translationDelta.X, 0, 0);
        //                        else
        //                            delta = new Vector3(translationDelta.X, translationDelta.Y, 0);
        //                    }
        //                }
        //                else if (ActiveAxis == GizmoAxis.Y || ActiveAxis == GizmoAxis.YZ || ActiveAxis == GizmoAxis.Z)
        //                {
        //                    Plane plane = new Plane(Vector3.Left, Vector3.Transform(position, Matrix.Invert(rotationMatrix)).X);

        //                    float? intersection = ray.Intersects(plane);
        //                    if (intersection.HasValue)
        //                    {
        //                        intersectPosition = (ray.Position + (ray.Direction * intersection.Value));
        //                        if (lastIntersectionPosition != Vector3.Zero)
        //                        {
        //                            translationDelta = intersectPosition - lastIntersectionPosition;
        //                        }
        //                        if (ActiveAxis == GizmoAxis.Y)
        //                            delta = new Vector3(0, translationDelta.Y, 0);
        //                        else if (ActiveAxis == GizmoAxis.Z)
        //                            delta = new Vector3(0, 0, translationDelta.Z);
        //                        else
        //                            delta = new Vector3(0, translationDelta.Y, translationDelta.Z);
        //                    }
        //                }
        //                else if (ActiveAxis == GizmoAxis.ZX)
        //                {
        //                    Plane plane = new Plane(Vector3.Down, Vector3.Transform(position, Matrix.Invert(rotationMatrix)).Y);

        //                    float? intersection = ray.Intersects(plane);
        //                    if (intersection.HasValue)
        //                    {
        //                        intersectPosition = (ray.Position + (ray.Direction * intersection.Value));
        //                        if (lastIntersectionPosition != Vector3.Zero)
        //                        {
        //                            translationDelta = intersectPosition - lastIntersectionPosition;
        //                        }
        //                    }

        //                    delta = new Vector3(translationDelta.X, 0, translationDelta.Z);
        //                }


        //                if (SnapEnabled)
        //                {
        //                    float snapValue = TranslationSnapValue;
        //                    if (ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale)
        //                        snapValue = ScaleSnapValue;
        //                    if (precisionMode)
        //                    {
        //                        delta *= precisionModeScale;
        //                        snapValue *= precisionModeScale;
        //                    }

        //                    translationScaleSnapDelta += delta;

        //                    delta = new Vector3(
        //                        (int)(translationScaleSnapDelta.X / snapValue) * snapValue,
        //                        (int)(translationScaleSnapDelta.Y / snapValue) * snapValue,
        //                        (int)(translationScaleSnapDelta.Z / snapValue) * snapValue);

        //                    translationScaleSnapDelta -= delta;
        //                }
        //                else if (precisionMode)
        //                    delta *= precisionModeScale;



        //                if (ActiveMode == GizmoMode.Translate)
        //                {
        //                    // transform (local or world)
        //                    delta = Vector3.Transform(delta, rotationMatrix);

        //                    // apply
        //                    foreach (SceneObject sceneObject in Selection)
        //                    {
        //                        sceneObject.WorldMatrix.Translation += delta;
        //                    }

        //                    // test vs. clamp
        //                    //if (((position + delta) - Engine.CameraPosition).Length() < translationClampDistance)
        //                    //{
        //                    // apply delta here.
        //                    //}
        //                    //else
        //                    //{
        //                    //    //reset
        //                    //    ActiveAxis = GizmoAxis.None;
        //                    //}
        //                }
        //                else if (ActiveMode == GizmoMode.NonUniformScale)
        //                {
        //                    // -- Apply Scale -- //
        //                    foreach (SceneObject sceneObject in this.Selection)
        //                    {
        //                        sceneObject.Scale += delta;
        //                        sceneObject.Scale = Vector3.Clamp(sceneObject.Scale, Vector3.Zero, sceneObject.Scale);
        //                    }
        //                }
        //                else if (ActiveMode == GizmoMode.UniformScale)
        //                {

        //                    float diff = 1 + ((delta.X + delta.Y + delta.Z) / 3);
        //                    foreach (SceneObject sceneObject in this.Selection)
        //                    {
        //                        sceneObject.Scale *= diff;

        //                        sceneObject.Scale = Vector3.Clamp(sceneObject.Scale, Vector3.Zero, sceneObject.Scale);
        //                    }
        //                }
        //                #endregion
        //            }
        //            else if (ActiveMode == GizmoMode.Rotate)
        //            {
        //                #region Rotate
        //                float delta = input.Mouse.Delta.X;
        //                delta *= inputScale;


        //                if (SnapEnabled)
        //                {
        //                    float snapValue = MathHelper.ToRadians(RotationSnapValue);
        //                    if (precisionMode)
        //                    {
        //                        delta *= precisionModeScale;
        //                        snapValue *= precisionModeScale;
        //                    }

        //                    rotationSnapDelta += delta;

        //                    float snapped = (int)(rotationSnapDelta / snapValue) * snapValue;
        //                    rotationSnapDelta -= snapped;

        //                    delta = snapped;
        //                }
        //                else if (precisionMode)
        //                {
        //                    delta *= precisionModeScale;
        //                }

        //                // rotation matrix to transform - if more than one objects selected, always use world-space.
        //                Matrix rot = Matrix.Identity;
        //                rot.Forward = sceneWorld.Forward;
        //                rot.Up = sceneWorld.Up;
        //                rot.Right = sceneWorld.Right;

        //                if (ActiveAxis == GizmoAxis.X)
        //                {
        //                    rot *= Matrix.CreateFromAxisAngle(rotationMatrix.Right, delta);
        //                }
        //                else if (ActiveAxis == GizmoAxis.Y)
        //                {
        //                    rot *= Matrix.CreateFromAxisAngle(rotationMatrix.Up, delta);
        //                }
        //                else if (ActiveAxis == GizmoAxis.Z)
        //                {
        //                    rot *= Matrix.CreateFromAxisAngle(rotationMatrix.Forward, delta);
        //                }

        //                // -- Apply rotation -- //
        //                foreach (SceneObject sceneObject in this.Selection)
        //                {
        //                    // use gizmo position for all PivotTypes except for object-center, it should use the entity.position instead.
        //                    Vector3 pos = position;
        //                    if (ActivePivot == PivotType.ObjectCenter)
        //                    {
        //                        pos = sceneObject.Position;
        //                    }

        //                    Matrix localRot = Matrix.Identity;
        //                    localRot.Forward = sceneObject.Forward;
        //                    localRot.Up = sceneObject.Up;
        //                    localRot.Right = Vector3.Cross(sceneObject.Forward, sceneObject.Up);
        //                    localRight.Normalize();
        //                    localRot.Translation = sceneObject.Position - pos;

        //                    Matrix newRot = localRot * rot;

        //                    sceneObject.Forward = newRot.Forward;
        //                    sceneObject.Up = newRot.Up;
        //                    sceneObject.Position = newRot.Translation + pos;

        //                }
        //                #endregion
        //            }
        //        }
        //        else
        //        {
        //            this.UpdateAxisSelection(input.Mouse.Position);
        //        }
        //    }

        //    // Enable only if something is selected.
        //    if (Selection.Count < 1)
        //        Enabled = false;
        //    else
        //        Enabled = true;
        //}

        /// <summary>
        /// Mouse move.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MouseMove(object sender, MouseEventArgs e)
        {
            lastIntersectionPosition = intersectPosition;

            if (e.Button == MouseButtons.Left && this.ActiveAxis != GizmoAxis.None)
            {
                if (this.ActiveMode == GizmoMode.Translate ||
                    this.ActiveMode == GizmoMode.NonUniformScale ||
                    this.ActiveMode == GizmoMode.UniformScale)
                {
                    #region Translate & Scale
                    Vector3 delta = Vector3.Zero;
                    Ray ray = ConvertMouseToRay(new Vector2(e.X, e.Y));

                    Matrix transform = Matrix.Invert(rotationMatrix);
                    ray.Position = Vector3.Transform(ray.Position, transform);
                    ray.Direction = Vector3.TransformNormal(ray.Direction, transform);


                    if (ActiveAxis == GizmoAxis.X || ActiveAxis == GizmoAxis.XY)
                    {
                        Plane plane = new Plane(Vector3.Forward, Vector3.Transform(position, Matrix.Invert(rotationMatrix)).Z);

                        float? intersection = ray.Intersects(plane);
                        if (intersection.HasValue)
                        {
                            intersectPosition = (ray.Position + (ray.Direction * intersection.Value));
                            if (lastIntersectionPosition != Vector3.Zero)
                            {
                                translationDelta = intersectPosition - lastIntersectionPosition;
                            }
                            if (ActiveAxis == GizmoAxis.X)
                                delta = new Vector3(translationDelta.X, 0, 0);
                            else
                                delta = new Vector3(translationDelta.X, translationDelta.Y, 0);
                        }
                    }
                    else if (ActiveAxis == GizmoAxis.Y || ActiveAxis == GizmoAxis.YZ || ActiveAxis == GizmoAxis.Z)
                    {
                        Plane plane = new Plane(Vector3.Left, Vector3.Transform(position, Matrix.Invert(rotationMatrix)).X);

                        float? intersection = ray.Intersects(plane);
                        if (intersection.HasValue)
                        {
                            intersectPosition = (ray.Position + (ray.Direction * intersection.Value));
                            if (lastIntersectionPosition != Vector3.Zero)
                            {
                                translationDelta = intersectPosition - lastIntersectionPosition;
                            }
                            if (ActiveAxis == GizmoAxis.Y)
                                delta = new Vector3(0, translationDelta.Y, 0);
                            else if (ActiveAxis == GizmoAxis.Z)
                                delta = new Vector3(0, 0, translationDelta.Z);
                            else
                                delta = new Vector3(0, translationDelta.Y, translationDelta.Z);
                        }
                    }
                    else if (ActiveAxis == GizmoAxis.ZX)
                    {
                        Plane plane = new Plane(Vector3.Down, Vector3.Transform(position, Matrix.Invert(rotationMatrix)).Y);

                        float? intersection = ray.Intersects(plane);
                        if (intersection.HasValue)
                        {
                            intersectPosition = (ray.Position + (ray.Direction * intersection.Value));
                            if (lastIntersectionPosition != Vector3.Zero)
                            {
                                translationDelta = intersectPosition - lastIntersectionPosition;
                            }
                        }

                        delta = new Vector3(translationDelta.X, 0, translationDelta.Z);
                    }


                    if (SnapEnabled)
                    {
                        float snapValue = TranslationSnapValue;
                        if (ActiveMode == GizmoMode.UniformScale || ActiveMode == GizmoMode.NonUniformScale)
                            snapValue = ScaleSnapValue;
                        if (precisionMode)
                        {
                            delta *= precisionModeScale;
                            snapValue *= precisionModeScale;
                        }

                        translationScaleSnapDelta += delta;

                        delta = new Vector3(
                            (int)(translationScaleSnapDelta.X / snapValue) * snapValue,
                            (int)(translationScaleSnapDelta.Y / snapValue) * snapValue,
                            (int)(translationScaleSnapDelta.Z / snapValue) * snapValue);

                        translationScaleSnapDelta -= delta;
                    }
                    else if (precisionMode)
                        delta *= precisionModeScale;



                    if (ActiveMode == GizmoMode.Translate)
                    {
                        // transform (local or world)
                        delta = Vector3.Transform(delta, rotationMatrix);

                        // apply
                        foreach (SceneObject sceneObject in SelectedObjects)
                            sceneObject.World = Matrix.CreateTranslation(delta) * sceneObject.World;
                        
                        // test vs. clamp
                        //if (((position + delta) - Engine.CameraPosition).Length() < translationClampDistance)
                        //{
                        // apply delta here.
                        //}
                        //else
                        //{
                        //    //reset
                        //    ActiveAxis = GizmoAxis.None;
                        //}
                    }/*
                    else if (ActiveMode == GizmoMode.NonUniformScale)
                    {
                        // -- Apply Scale -- //
                        foreach (SceneObject sceneObject in this.Selection)
                        {
                            sceneObject.Scale += delta;
                            sceneObject.Scale = Vector3.Clamp(sceneObject.Scale, Vector3.Zero, sceneObject.Scale);
                        }
                    }
                    else if (ActiveMode == GizmoMode.UniformScale)
                    {

                        float diff = 1 + ((delta.X + delta.Y + delta.Z) / 3);
                        foreach (SceneObject sceneObject in this.Selection)
                        {
                            sceneObject.Scale *= diff;

                            sceneObject.Scale = Vector3.Clamp(sceneObject.Scale, Vector3.Zero, sceneObject.Scale);
                        }
                    }*/
                    #endregion
                }/*
                else if (ActiveMode == GizmoMode.Rotate)
                {
                    #region Rotate
                    float delta = input.Mouse.Delta.X;
                    delta *= inputScale;


                    if (SnapEnabled)
                    {
                        float snapValue = MathHelper.ToRadians(RotationSnapValue);
                        if (precisionMode)
                        {
                            delta *= precisionModeScale;
                            snapValue *= precisionModeScale;
                        }

                        rotationSnapDelta += delta;

                        float snapped = (int)(rotationSnapDelta / snapValue) * snapValue;
                        rotationSnapDelta -= snapped;

                        delta = snapped;
                    }
                    else if (precisionMode)
                    {
                        delta *= precisionModeScale;
                    }

                    // rotation matrix to transform - if more than one objects selected, always use world-space.
                    Matrix rot = Matrix.Identity;
                    rot.Forward = sceneWorld.Forward;
                    rot.Up = sceneWorld.Up;
                    rot.Right = sceneWorld.Right;

                    if (ActiveAxis == GizmoAxis.X)
                    {
                        rot *= Matrix.CreateFromAxisAngle(rotationMatrix.Right, delta);
                    }
                    else if (ActiveAxis == GizmoAxis.Y)
                    {
                        rot *= Matrix.CreateFromAxisAngle(rotationMatrix.Up, delta);
                    }
                    else if (ActiveAxis == GizmoAxis.Z)
                    {
                        rot *= Matrix.CreateFromAxisAngle(rotationMatrix.Forward, delta);
                    }

                    // -- Apply rotation -- //
                    foreach (SceneObject sceneObject in this.Selection)
                    {
                        // use gizmo position for all PivotTypes except for object-center, it should use the entity.position instead.
                        Vector3 pos = position;
                        if (ActivePivot == PivotType.ObjectCenter)
                        {
                            pos = sceneObject.Position;
                        }

                        Matrix localRot = Matrix.Identity;
                        localRot.Forward = sceneObject.Forward;
                        localRot.Up = sceneObject.Up;
                        localRot.Right = Vector3.Cross(sceneObject.Forward, sceneObject.Up);
                        localRight.Normalize();
                        localRot.Translation = sceneObject.Position - pos;

                        Matrix newRot = localRot * rot;

                        sceneObject.Forward = newRot.Forward;
                        sceneObject.Up = newRot.Up;
                        sceneObject.Position = newRot.Translation + pos;

                    }
                    #endregion
                }*/
            }
            else
                this.UpdateAxisSelection(new Vector2(e.X, e.Y));
        }

        /// <summary>
        /// Mouse click.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MouseClick(object sender, MouseEventArgs e)
        {
         
        }

        /// <summary>
        /// Mouse down.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MouseDown(object sender, MouseEventArgs e)
        {
            
        }

        /// <summary>
        /// Mouse Up.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                // reset for intersection (plane vs. ray)
                intersectPosition = Vector3.Zero;
                // reset for snapping
                translationScaleSnapDelta = Vector3.Zero;
                //rotationSnapDelta = 0;
            }

            lastIntersectionPosition = intersectPosition;
        }

        /// <summary>
        /// Helper method for applying color to the gizmo lines.
        /// </summary>
        private void ApplyColor(GizmoAxis axis, Color color)
        {
            if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale)
            {
                switch (axis)
                {
                    case GizmoAxis.X:
                        ApplyLineColor(0, 6, color);
                        break;
                    case GizmoAxis.Y:
                        ApplyLineColor(6, 6, color);
                        break;
                    case GizmoAxis.Z:
                        ApplyLineColor(12, 6, color);
                        break;
                    case GizmoAxis.XY:
                        ApplyLineColor(0, 4, color);
                        ApplyLineColor(6, 4, color);
                        break;
                    case GizmoAxis.YZ:
                        ApplyLineColor(6, 2, color);
                        ApplyLineColor(12, 2, color);
                        ApplyLineColor(10, 2, color);
                        ApplyLineColor(16, 2, color);
                        break;
                    case GizmoAxis.ZX:
                        ApplyLineColor(0, 2, color);
                        ApplyLineColor(4, 2, color);
                        ApplyLineColor(12, 4, color);
                        break;
                }
            }
            else if (ActiveMode == GizmoMode.Rotate)
            {
                switch (axis)
                {
                    case GizmoAxis.X:
                        ApplyLineColor(0, 6, color);
                        break;
                    case GizmoAxis.Y:
                        ApplyLineColor(6, 6, color);
                        break;
                    case GizmoAxis.Z:
                        ApplyLineColor(12, 6, color);
                        break;
                }
            }
            else if (ActiveMode == GizmoMode.UniformScale)
            {
                // all three axis red.
                if (ActiveAxis == GizmoAxis.None)
                    ApplyLineColor(0, this.AxisDrawCall.Vertices.Length, axisColors[0]);
                else
                    ApplyLineColor(0, this.AxisDrawCall.Vertices.Length, highlightColor);
            }
        }

        /// <summary>
        /// Apply color on the lines associated with translation mode (re-used in Scale)
        /// </summary>
        private void ApplyLineColor(int startindex, int count, Color color)
        {
            for (int i = startindex; i < (startindex + count); i++)
            {
                this.AxisDrawCall.Vertices[i].Color = color;
            }
        }

        /// <summary>
        /// Per-frame check to see if mouse is hovering over any axis.
        /// </summary>
        private void UpdateAxisSelection(Vector2 mousePosition)
        {
            float closestintersection = float.MaxValue;
            Ray ray = ConvertMouseToRay(mousePosition);

            closestintersection = float.MaxValue;
            float? intersection;

            if (ActiveMode == GizmoMode.Translate || ActiveMode == GizmoMode.NonUniformScale || ActiveMode == GizmoMode.UniformScale)
            {
                #region BoundingBoxes

                intersection = XY_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.XY;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = XZ_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.ZX;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = YZ_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.YZ;
                        closestintersection = intersection.Value;
                    }
                }

                intersection = X_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.X;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = Y_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.Y;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = Z_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.Z;
                        closestintersection = intersection.Value;
                    }
                }

                #endregion
            }

            if (this.ActiveMode == GizmoMode.Rotate || 
                this.ActiveMode == GizmoMode.UniformScale ||
                this.ActiveMode == GizmoMode.NonUniformScale)
            {
                #region BoundingSpheres

                intersection = X_Sphere.Intersects(ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.X;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = Y_Sphere.Intersects(ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.Y;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = Z_Sphere.Intersects(ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.Z;
                        closestintersection = intersection.Value;
                    }
                }


                #endregion
            }

            if (ActiveMode == GizmoMode.Rotate)
            {
                #region X,Y,Z Boxes
                intersection = X_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.X;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = Y_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.Y;
                        closestintersection = intersection.Value;
                    }
                }
                intersection = Z_Box.Intersects(ref ray);
                if (intersection.HasValue)
                {
                    if (intersection.Value < closestintersection)
                    {
                        ActiveAxis = GizmoAxis.Z;
                        closestintersection = intersection.Value;
                    }
                }
                #endregion
            }

            if (closestintersection == float.MaxValue)
                this.ActiveAxis = GizmoAxis.None;
        }

        /// <summary>
        /// Converts the 2D mouse position to a 3D ray for collision tests.
        /// </summary>
        public Ray ConvertMouseToRay(Vector2 mousePosition)
        {

            Vector3 nearPoint = new Vector3(mousePosition, 0);
            Vector3 farPoint = new Vector3(mousePosition, 1);

            Viewport tempViewport = new Viewport(0, 0, this.Viewport.PositionSize.Width, this.Viewport.PositionSize.Height);

            nearPoint = tempViewport.Unproject(nearPoint, this.Viewport.Camera.ProjectionMatrix, this.Viewport.Camera.ViewMatrix, Matrix.Identity);
            farPoint = tempViewport.Unproject(farPoint, this.Viewport.Camera.ProjectionMatrix, this.Viewport.Camera.ViewMatrix, Matrix.Identity);

            Vector3 direction = farPoint - nearPoint;
            direction.Normalize();

            return new Ray(nearPoint, direction);
        }

        /// <summary>
        /// Select objects inside level. Very simple example. Should be replaced by your own code, more fit for your custom editors.
        /// </summary>
        private void PickObject(Vector2 mousePosition, bool removeFromSelection)
        {
            /*
            Ray ray = ConvertMouseToRay(mousePosition);
            foreach (SceneEntity entity in Engine.Entities)
            {
                if (entity.BoundingBox.Intersects(ray).HasValue)
                {
                    if (!Selection.Contains(entity))
                    {
                        Selection.Add(entity);
                        break;
                    }
                    else
                    {
                        if (removeFromSelection)
                            Selection.Remove(entity);
                    }
                }
            }*/
        }

        /// <summary>
        /// Set position of the gizmo, position will be center of all selected entities.
        /// </summary>
        private void SetPosition()
        {
            this.position = Vector3.Zero;

            foreach (SceneObject sceneObject in this.SelectedObjects)            
                this.position += sceneObject.World.Translation;
            
            if (this.SelectedObjects.Count > 0)
                this.position /= this.SelectedObjects.Count;             
        }        

        /// <summary>
        /// Method draws object.
        /// </summary>
        public override void  AddInRenderingPipeline(RenderingPipeline renderingPipeline, Camera camera)
        { 	 
            if (this.Visible)
            {                
                renderingPipeline.AddOpaqueGraphicsObject(this.VertexColorDrawCallKey, this.AxisDrawCall, this.World);                    
                                
                if (this.ActiveMode == GizmoMode.Translate || this.ActiveMode == GizmoMode.NonUniformScale)
                {
                    if (this.ActiveAxis == GizmoAxis.XY)
                        renderingPipeline.AddOpaqueGraphicsObject(this.AxeXColorDrawCallKey, this.Quads[0], this.World);
                    else
                        if (this.ActiveAxis == GizmoAxis.ZX)
                            renderingPipeline.AddOpaqueGraphicsObject(this.AxeXColorDrawCallKey, this.Quads[1], this.World);
                        else
                            if (this.ActiveAxis == GizmoAxis.YZ)
                                renderingPipeline.AddOpaqueGraphicsObject(this.AxeXColorDrawCallKey, this.Quads[2], this.World);

                    if (this.ActiveMode == GizmoMode.Translate)
                        for (int i = 0; i < 3; i++)
                            this.ConeModel.AddInRenderingPipeline(renderingPipeline, camera, this.ModelLocalSpace[i] * this.World);                    
                    else
                    {/*
                        // -- Draw Boxes -- //
                        for (int i = 0; i < 3; i++) // 3 = nr. of axis (order: x, y, z)
                        {
                            foreach (ModelMesh mesh in scaleModel.Meshes)
                            {
                                foreach (ModelMeshPart meshpart in mesh.MeshParts)
                                {
                                    BasicEffect effect = (BasicEffect)meshpart.Effect;
                                    Vector3 color = axisColors[i].ToVector3();

                                    effect.World = modelLocalSpace[i] * gizmoWorld;
                                    effect.DiffuseColor = color;
                                    effect.EmissiveColor = color;

                                    effect.EnableDefaultLighting();

                                    effect.View = this.Viewport.Camera.ViewMatrix;
                                    effect.Projection = this.Viewport.Camera.ProjectionMatrix;
                                }
                                mesh.Draw();
                            }
                        }*/
                    }                    
                }/*
                else if (ActiveMode == GizmoMode.Rotate)
                {
                    #region Rotate
                    // -- Draw Circle-Arrows -- //
                    for (int i = 0; i < 3; i++) // 3 = nr. of axis (order: x, y, z)
                    {
                        foreach (ModelMesh mesh in rotationModel.Meshes)
                        {
                            foreach (ModelMeshPart meshpart in mesh.MeshParts)
                            {
                                BasicEffect effect = (BasicEffect)meshpart.Effect;
                                Vector3 color = axisColors[i].ToVector3();

                                effect.World = modelLocalSpace[i] * gizmoWorld;
                                effect.DiffuseColor = color;
                                effect.EmissiveColor = color;


                                effect.View = this.Viewport.Camera.ViewMatrix;
                                effect.Projection = this.Viewport.Camera.ProjectionMatrix;
                            }
                            mesh.Draw();
                        }
                    }
                    #endregion
                }
                else if (ActiveMode == GizmoMode.UniformScale)
                {
                    #region UniformScale
                    // -- Draw Boxes -- //
                    for (int i = 0; i < 3; i++) // 3 = nr. of axis (order: x, y, z)
                    {
                        foreach (ModelMesh mesh in scaleModel.Meshes)
                        {
                            foreach (ModelMeshPart meshpart in mesh.MeshParts)
                            {
                                BasicEffect effect = (BasicEffect)meshpart.Effect;
                                Vector3 color = axisColors[0].ToVector3(); //- all using the same color (red)

                                effect.World = modelLocalSpace[i] * gizmoWorld;
                                effect.DiffuseColor = color;
                                effect.EmissiveColor = color;

                                effect.EnableDefaultLighting();

                                effect.View = this.Viewport.Camera.ViewMatrix;
                                effect.Projection = this.Viewport.Camera.ProjectionMatrix;
                            }
                            mesh.Draw();
                        }
                    }

                    if (ActiveAxis != GizmoAxis.None)
                    {
                        ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.BlendState = BlendState.AlphaBlend;
                        ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullNone;

                        quadEffect.World = gizmoWorld;
                        quadEffect.View = this.Viewport.Camera.ViewMatrix;
                        quadEffect.Projection = this.Viewport.Camera.ProjectionMatrix;

                        quadEffect.CurrentTechnique.Passes[0].Apply();

                        for (int i = 0; i < quads.Length; i++)
                        {
                            ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
                                quads[i].Vertices, 0, 4,
                                quads[i].Indexes, 0, 2);
                        }

                        ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.BlendState = BlendState.Opaque;
                        ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
                    }
                    #endregion
                }

                ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
                 */
            }
        }        
    }

    /// <summary>
    /// Gizmo axis.
    /// </summary>
    public enum GizmoAxis
    {
        X,
        Y,
        Z,
        XY,
        ZX,
        YZ,
        None
    }

    /// <summary>
    /// Gizmo mode.
    /// </summary>
    public enum GizmoMode
    {
        Translate,
        Rotate,
        NonUniformScale,
        UniformScale
    }    

    /// <summary>
    /// Pivot type.
    /// </summary>
    public enum PivotType
    {
        ObjectCenter,
        SelectionCenter,
        WorldOrigin
    }
}
